package org.hawk.gwt.ppc.reflect.lang;

import java.io.Serializable;

import java.lang.reflect.Modifier;
import java.util.Arrays;

import org.hawk.gwt.ppc.reflect.lang.mock.Mock1;
import org.hawk.gwt.ppc.reflect.lang.mock.Mock2;
import org.hawk.gwt.ppc.reflect.lang.mock.Mock3;

import junit.framework.TestCase;

@SuppressWarnings("unchecked")
public class ClassDelegateTestCase extends TestCase {
	protected void setUp() throws Exception {
		ReflectionTestHelper.initialize();
	}

	public void testForName() throws ClassNotFoundException{
		try{
			ClassDelegate.forName("org.hawk.gwt.ppc.reflect.lang.ClassDelegateTestCase");
		}
		catch(ClassNotFoundException ex){}
		
		assertEquals(Mock1.$class, ClassDelegate.forName(
			"org.hawk.gwt.ppc.reflect.lang.mock.Mock1"));
		assertNotNull(Mock1.$class.getClassLoader());
	}
	
	public void testNewInstance() throws ClassNotFoundException, 
			IllegalAccessException, InstantiationException{
		ClassDelegate<Mock1> c = (ClassDelegate<Mock1>)ClassDelegate
			.forName("org.hawk.gwt.ppc.reflect.lang.mock.Mock1");
		assertNotNull(c.newInstance());
		assertTrue(c.newInstance() instanceof Mock1);
		try{
			ClassDelegate.forName(
				"org.hawk.gwt.ppc.reflect.lang.mock.Mock2")
				.newInstance();
			fail("Interface!");
		}
		catch(InstantiationException ex){}
	}
	
	public void testIsInstance() throws ClassNotFoundException{
		ClassDelegate<Mock1> c = (ClassDelegate<Mock1>)ClassDelegate
			.forName("org.hawk.gwt.ppc.reflect.lang.mock.Mock1");
		assertTrue(c.isInstance(new Mock1()));
		assertFalse(c.isInstance(new String()));
		assertTrue(c.isInstance(new Mock3()));
	}
	
	public void testIsAssignableFrom() throws ClassNotFoundException{
		ClassDelegate<Mock1> c1 = (ClassDelegate<Mock1>)ClassDelegate
			.forName("org.hawk.gwt.ppc.reflect.lang.mock.Mock1");
		ClassDelegate<Mock2> c2 = (ClassDelegate<Mock2>)ClassDelegate
			.forName("org.hawk.gwt.ppc.reflect.lang.mock.Mock2");
		ClassDelegate<Mock3> c3 = (ClassDelegate<Mock3>)ClassDelegate
			.forName("org.hawk.gwt.ppc.reflect.lang.mock.Mock3");
		assertTrue(c2.isAssignableFrom(c3));
		assertFalse(c2.isAssignableFrom(c1));
		assertFalse(c3.isAssignableFrom(c1));
		assertTrue(c1.isAssignableFrom(c3));
		assertFalse(c1.isAssignableFrom(c2));
	}
	
	public void testIsInterface() throws ClassNotFoundException{
		ClassDelegate<Mock1> c1 = (ClassDelegate<Mock1>)ClassDelegate
			.forName("org.hawk.gwt.ppc.reflect.lang.mock.Mock1");
		ClassDelegate<Mock2> c2 = (ClassDelegate<Mock2>)ClassDelegate
			.forName("org.hawk.gwt.ppc.reflect.lang.mock.Mock2");
		ClassDelegate<Mock3> c3 = (ClassDelegate<Mock3>)ClassDelegate
			.forName("org.hawk.gwt.ppc.reflect.lang.mock.Mock3");
		assertFalse(c1.isInterface());
		assertTrue(c2.isInterface());
		assertFalse(c3.isInterface());
	}
	
	public void testIsPrimitive(){
		ClassDelegate<String> c1 = ClassDelegate.forClass(String.class);
		ClassDelegate<Integer> c2 = ClassDelegate.forClass(int.class);
		ClassDelegate<Mock1> c3 = ClassDelegate.forClass(Mock1.class);
		assertFalse(c1.isPrimitive());
		assertTrue(c2.isPrimitive());
		assertFalse(c3.isPrimitive());
	}
	
	public void testGetName(){
		ClassDelegate<String> c1 = ClassDelegate.forClass(String.class);
		ClassDelegate<Integer> c2 = ClassDelegate.forClass(int.class);
		ClassDelegate<Mock1> c3 = ClassDelegate.forClass(Mock1.class);
		assertEquals(String.class.getName(), c1.getName());
		assertEquals(int.class.getName(), c2.getName());
		assertEquals(Mock1.class.getName(), c3.getName());
	}
	
	public void testGetClassLoader(){
		ClassDelegate<String> c1 = ClassDelegate.forClass(String.class);
		ClassDelegate<Integer> c2 = ClassDelegate.forClass(int.class);
		ClassDelegate<Mock1> c3 = ClassDelegate.forClass(Mock1.class);
		assertNotNull(c1.getClassLoader());
		assertNotNull(c2.getClassLoader());
		assertNotNull(c3.getClassLoader());
	}
	
	public void testGetSuperclass(){
		ClassDelegate<Mock3> c3 = ClassDelegate.forClass(Mock3.class);
		assertEquals(Mock1.$class, c3.getSuperclass());
	}
	
	public void testGetInterfaces(){
		ClassDelegate<Mock1> c1 = ClassDelegate.forClass(Mock1.class);
		ClassDelegate<Mock3> c3 = ClassDelegate.forClass(Mock3.class);
		assertTrue(c1.getInterfaces().length==0);
		assertTrue(Arrays.equals(c3.getInterfaces(),new ClassDelegate[]{
			ClassDelegate.forClass(Serializable.class), Mock2.$class
		}));
	}
	
	public void testGetModifiers(){
		ClassDelegate<Mock1> c1 = ClassDelegate.forClass(Mock1.class);
		ClassDelegate<Mock3> c3 = ClassDelegate.forClass(Mock3.class);
		assertTrue((c1.getModifiers()&Modifier.PUBLIC)>0);
		assertTrue((c3.getModifiers()&Modifier.PUBLIC)>0);
	}
	
	public void testGetSimpleName(){
		ClassDelegate<Mock1> c1 = ClassDelegate.forClass(Mock1.class);
		ClassDelegate<Mock3> c3 = ClassDelegate.forClass(Mock3.class);
		assertEquals("Mock1", c1.getSimpleName());
		assertEquals("Mock3", c3.getSimpleName());
	}
}
